#!/bin/bash
######################################################################################
#
# Process name    : System Health Check report
# File name       : system_health_check_report.sh
# Output file     : /tmp/system_health_check_report.txt
# Change History  :
# Date             Edited By         Comment
# 2020/9/11       Mo               Created
#
######################################################################################

#global_description
. /etc/profile
A_RELEASE=$(cat /etc/redhat-release |awk '{print $(NF-1)}'|awk -F"." '{print $1}')
A_HOSTNAME=$(hostname)
A_OS_VERSION=$(cat /etc/redhat-release)
A_DATA_TIME=$(date "+%Y/%m/%d %H:%M:%S")

# check_host_type
check_host_type()
{

HOST_TYPE=$(/usr/sbin/dmidecode -t 1|grep Manufacturer|awk -F: '{print $2}'|awk -F, '{print $1}')

}

#check_runlevel
get_ip_address ()
{
DEFAULT_ROUTR=`/sbin/ip route|grep -w ^default|awk '{print $3}'|awk -F . '{print $1"."$2"."$3}'`
A_ADDRESS=`/sbin/ip addr|grep -w $DEFAULT_ROUTR|sed -n 1p|awk '{print $2}'|awk -F / '{print $1}'`

}

#check_runlevel
check_runlevel ()
{
A_RUNLEVEL=$(runlevel |awk -F" " '{print $NF}')
if [ $? -eq 0 ];then
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Runlevel: ${A_RUNLEVEL}"
else
  A_RUNLEVEL=$(echo "NONE")
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Runlevel: ${A_RUNLEVEL}"
fi

}

#check_filesystem_space
check_filesystem_space()
{
FILE_BEYOND_NUM=$(df -h|egrep -i "9[0-9]%|100%"|awk '{print $NF,$(NF-1)}'|wc -l)
FILE_BEYOND_MAX=$(df -h|egrep -i "9[0-9]%|100%"|awk '{print $NF,$(NF-1)}'|sort -rnk2|sed -n 1p)

if [ "${FILE_BEYOND_NUM}" -eq 0 ];then
  FILE_BEYOND_NUM=$(echo "NONE")
  FILE_BEYOND_MAX=$(echo "NONE")
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Filesystem_Space: [>90%]Number:${FILE_BEYOND_NUM},Max:${FILE_BEYOND_MAX}"
else
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Filesystem_Space: [>90%]Number:${FILE_BEYOND_NUM},Max:${FILE_BEYOND_MAX}"
fi

}

#check_filesystem_inode_space
check_filesystem_inode_space()
{
FILE_BEYOND_INODE_NUM=$(df -ih|egrep -i "9[0-9]%|100%"|awk '{print $NF,$(NF-1)}'|wc -l)
FILE_BEYOND_INODE_MAX=$(df -ih|egrep -i "9[0-9]%|100%"|awk '{print $NF,$(NF-1)}'|sort -rnk2|sed -n 1p)

if [ "${FILE_BEYOND_INODE_NUM}" -eq 0 ];then
  FILE_BEYOND_INODE_NUM=$(echo "NONE")
  FILE_BEYOND_INODE_MAX=$(echo "NONE")
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Filesystem_Inode_Space: [>90%]Number:${FILE_BEYOND_INODE_NUM},Max:${FILE_BEYOND_INODE_MAX}"
else
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Filesystem_Inode_Space: [>90%]Number:${FILE_BEYOND_INODE_NUM},Max:${FILE_BEYOND_INODE_MAX}"
fi

}

#check_cpu_load
check_cpu_load()
{
if [ "${A_RELEASE}" -eq 7 ];then
  CPU_IDLE=$(echo $(sar -u 1 2|grep Average|awk '{print $NF}')%)
else
  CPU_IDLE=$(echo $(vmstat|grep -v procs|awk '{print $(NF-2)}'|sed -n 2p)%)
fi

echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_CPU_Load_Idle: ${CPU_IDLE}"

}

#check_memory_space
check_memory_space()
{
M_TOTAL=$(cat /proc/meminfo |grep "^MemTotal"|awk '{print $(NF-1)}')
M_FREE=$(cat /proc/meminfo |grep "^MemFree"|awk '{print $(NF-1)}')
M_BUFFER=$(cat /proc/meminfo |grep "^Buffers"|awk '{print $(NF-1)}')
M_CACHE=$(cat /proc/meminfo |grep "^Cached"|awk '{print $(NF-1)}')
REAL_MEMORY=$(awk 'BEGIN{printf"%.2f%\n",('${M_TOTAL}'-'${M_FREE}'-'${M_BUFFER}'-'${M_CACHE}')/'${M_TOTAL}'*100}')

echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Real_Memory_Use_Space: ${REAL_MEMORY}"
}

#check_swap_space
check_swap_space()
{
SWAP_TOTAL=$(cat /proc/meminfo |grep "^SwapTotal"|awk '{print $(NF-1)}')
SWAP_FREE=$(cat /proc/meminfo |grep "^SwapFree"|awk '{print $(NF-1)}')
SWAP_USE=$(awk 'BEGIN{printf"%.2f%\n",('${SWAP_TOTAL}'-'${SWAP_FREE}')/'${SWAP_TOTAL}'*100}')

echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Swap_Use_Space: ${SWAP_USE}"
}

#check_threads_number
check_threads_number()
{
NUM_THREADS=$(ps -eLf|wc -l)

echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Threads_Number: ${NUM_THREADS}"

}


#check_zombie_number
check_zombie_number()
{
NUM_ZOMBIE=$(ps -Ao stat,pid,ppid,cmd | grep -e '^[zZ]'|wc -l)
if [[ ${NUM_ZOMBIE} -eq 0 ]];then
  NUM_ZOMBIE=$(echo "NONE")
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Zombie_Number: ${NUM_ZOMBIE}"
else
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Zombie_Number: ${NUM_ZOMBIE}"
fi

}

# check_dns_service
check_dns_service()
{
DNS_SERVICE=$(cat /etc/resolv.conf|grep nameserver|awk '{print $2}' | awk BEGIN{RS=EOF}'{gsub(/\n/,",");print}' )
DNS_SERVICE_NUM=$(cat /etc/resolv.conf|grep nameserver|awk '{print $2}' | awk BEGIN{RS=EOF}'{gsub(/\n/,",");print}' |wc -l)
if [[ ${DNS_SERVICE_NUM} -eq 0 ]];then
  DNS_SERVICE=$(echo "NONE")
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_DNS_Service: ${DNS_SERVICE}"
else
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_DNS_Service: ${DNS_SERVICE}"
fi

}

#check_timesync_serivce
check_timesync_serivce()
{
if [ "${A_RELEASE}" -eq 7 ];then
  chronyc sources|grep -e "^\^\*" >/dev/null 2>&1
  SYNC_RETUN_CODE1=$?
  if [ "${SYNC_RETUN_CODE1}" -eq 0 ];then
    S_TIMESYNC=$(echo "CHRONYD OK")
	echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Timesync_Serivce: ${S_TIMESYNC}"
  else
    S_TIMESYNC=$(echo "ERROR")
	echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Timesync_Serivce: ${S_TIMESYNC}"
  fi
else
  ntpq -pn|grep -e "^\*" >/dev/null 2>&1
  SYNC_RETUN_CODE2=$?
  if [[ ${SYNC_RETUN_CODE2} -eq 0 ]];then
    S_TIMESYNC=$(echo "NTPD OK")
	echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_TimeSync_Serivce: ${S_TIMESYNC}"
  else
    S_TIMESYNC=$(echo "ERROR")
	echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_TimeSync_Serivce: ${S_TIMESYNC}"
  fi
fi
}

#check_selinux_mode
check_selinux_mode()
{
getenforce > /dev/null 2>&1
if [ $? -eq 0 ];then
  GET_SELINUX=$(getenforce)
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_SElinux_Mode: ${GET_SELINUX}"
else
  GET_SELINUX=$(echo "ERROR")
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_SElinux_Mode: ${GET_SELINUX}"
fi

}

#check_umask_mode
check_umask_mode()
{
GET_UMASK=$(umask)
echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Umask_Mode: ${GET_UMASK}"
}

#check_firewalld
check_firewalld()
{
FIREWALLD_ACTIVE=$(/usr/bin/systemctl is-active firewalld.service )
FIREWALLD_ENABLE=$(/usr/bin/systemctl is-enabled firewalld.service )

if [[ ${FIREWALLD_ACTIVE} == "active" ]] && [[ ${FIREWALLD_ENABLE} == "enabled" ]]; then
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Firewalld: OK"
else
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Firewalld: ${FIREWALLD_ACTIVE},${FIREWALLD_ENABLE}"
fi

}

#check_networkmanager
check_NetworkManager()
{
NetworkManager_ACTIVE=$(/usr/bin/systemctl is-active NetworkManager.service )
NetworkManager_ENABLE=$(/usr/bin/systemctl is-enabled NetworkManager.service )

if [[ ${NetworkManager_ACTIVE} == "active" ]] && [[ ${NetworkManager_ENABLE} == "enabled" ]]; then
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_NetworkManager: OK"
else
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_NetworkManager: ${NetworkManager_ACTIVE},${NetworkManager_ENABLE}"
fi

}

#check_filesystem_readonly_number
check_filesystem_readonly_number()
{
FILE_READ_ONLY=$(grep -w 'ro' /proc/mounts | egrep -v 'automount|autofs|iso9660|tmpfs'|wc -l)
if [ "${FILE_READ_ONLY}" -eq 0 ];then
  FILE_READ_ONLY=$(echo "NONE")
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Filesystem_Readonly_Number: ${FILE_READ_ONLY}"
else
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Filesystem_Readonly_Number: ${FILE_READ_ONLY}"
fi
}

# check_password_complexity
check_password_complexity()
{
PASSWORD_COMPLEXITY="minlen=8 dcredit=-1 ucredit=-1 ocredit=-1 lcredit=-1"
PASSWORD_COMPLEXITY_SYSTEM=$(cat /etc/pam.d/system-auth |egrep -v "^#|^$"|grep "${PASSWORD_COMPLEXITY}" |wc -l )
PASSWORD_COMPLEXITY_PASSWORD=$(cat /etc/pam.d/password-auth |egrep -v "^#|^$" |grep "${PASSWORD_COMPLEXITY}" |wc -l )
if [ "${PASSWORD_COMPLEXITY_SYSTEM}" -eq 1 ] && [ "${PASSWORD_COMPLEXITY_PASSWORD}" -eq 1 ]; then
  PASSWORD_COMPLEXITY_STATUS=$(echo "OK")
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Password_Complexity: OK"
else
  PASSWORD_COMPLEXITY_STATUS=$(echo "ERROR")
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Password_Complexity: ERROR"
fi
}

# check_maximum_password_survival
check_maximum_password_survival()
{
Password_Survival_DAY=$(cat /etc/login.defs |egrep -v "^#|^$"|grep 'PASS_MAX_DAYS'|grep 90|wc -l)
Password_Survival_LEN=$(cat /etc/login.defs |egrep -v "^#|^$"|grep 'PASS_MIN_LEN'|grep 8|wc -l)
Password_Survival_AGE=$(cat /etc/login.defs |egrep -v "^#|^$"|grep 'PASS_WARN_AGE'|grep 15|wc -l)
if [ "${Password_Survival_DAY}" -eq 1 ] && [ "${Password_Survival_LEN}" -eq 1 ] && [ "${Password_Survival_AGE}" -eq 1 ]; then
  Password_Survival_Status=$(echo "OK")
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Maximum_Password_Survival: OK"
else
  Password_Survival_Status=$(echo "ERROR")
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Maximum_Password_Survival: ERROR"
fi
}

# check_login_failed_account_lock
check_login_failed_account_lock()
{
LOGIN_FAILED_CONFIG1=$(grep 'auth        required      pam_faillock.so preauth silent audit deny=10 unlock_time=3600' /etc/pam.d/system-auth |wc -l)
LOGIN_FAILED_CONFIG2=$(grep 'auth        \[default\=die\] pam_faillock.so authfail audit deny=10 unlock_time=3600' /etc/pam.d/system-auth |wc -l)
LOGIN_FAILED_CONFIG3=$(grep 'account     required      pam_faillock.so' /etc/pam.d/system-auth |wc -l)
LOGIN_FAILED_CONFIG4=$(grep 'auth        required      pam_faillock.so preauth silent audit deny=10 unlock_time=3600' /etc/pam.d/password-auth |wc -l)
LOGIN_FAILED_CONFIG5=$(grep 'auth        \[default\=die\] pam_faillock.so authfail audit deny=10 unlock_time=3600' /etc/pam.d/password-auth |wc -l)
LOGIN_FAILED_CONFIG6=$(grep 'account     required      pam_faillock.so' /etc/pam.d/password-auth |wc -l)

if [ "${LOGIN_FAILED_CONFIG1}" -eq 1 ] && [ "${LOGIN_FAILED_CONFIG2}" -eq 1 ] && [ "${LOGIN_FAILED_CONFIG3}" -eq 1 ] && [ "${LOGIN_FAILED_CONFIG4}" -eq 1 ] && [ "${LOGIN_FAILED_CONFIG5}" -eq 1 ] && [ "${LOGIN_FAILED_CONFIG6}" -eq 1 ]; then
  Login_Failed_Account_Lock_Status=$(echo "OK")
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Login_Failed_Account_Lock: OK"
else
  Login_Failed_Account_Lock_Status=$(echo "ERROR")
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Login_Failed_Account_Lock: ERROR"
fi
}

# check_root_remote_login
check_root_remote_login()
{
REMOTE_LOGIN=$(cat /etc/ssh/sshd_config |grep -v ^# |grep 'PermitRootLogin no'|wc -l)
if [ "${REMOTE_LOGIN}" -eq 1 ] ; then
  Root_Remote_Login_Status=$(echo "OK")
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Root_Remote_Login: OK"
else
  Root_Remote_Login_Status=$(echo "ERROR")
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Root_Remote_Login: ERROR"
fi
}

# check_redundant_account_lockdown
check_redundant_account_lockdown()
{
Redundant_Account=$(for user in bin daemon adm lp sync shutdown halt mail operator games ftp nobody systemd-network dbus polkitd tss abrt sshd postfix;do /usr/bin/passwd -S "$user" |grep 'in use';done|wc -l)

if [ "${Redundant_Account}" -eq 0 ] ; then
  Redundant_Account_Lockdown_Status=$(echo "OK")
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Redundant_Account_Lockdown: OK"
else
  Redundant_Account_Lockdown_Status=$(echo "ERROR")
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Redundant_Account_Lockdown: ERROR"
fi
}

# check_system_key_file_permissions_control
check_system_key_file_permissions_control()
{
passwdPerm1=$(stat /etc/passwd|grep Access|grep Uid|awk -F: '{print $2}'|awk -F'/' '{print $1}'|tr -cd "[0-9]")
groupPerm2=$(stat /etc/group |grep Access|grep Uid|awk -F: '{print $2}'|awk -F'/' '{print $1}'|tr -cd "[0-9]")
mountPerm3=$(stat /bin/mount |grep Access|grep Uid|awk -F: '{print $2}'|awk -F'/' '{print $1}'|tr -cd "[0-9]")
umountPerm4=$(stat /bin/umount  |grep Access|grep Uid|awk -F: '{print $2}'|awk -F'/' '{print $1}'|tr -cd "[0-9]")
crontabPerm5=$(stat /etc/crontab |grep Access|grep Uid|awk -F: '{print $2}'|awk -F'/' '{print $1}'|tr -cd "[0-9]")
grubPerm6=$(stat /boot/grub2/grub.cfg  |grep Access|grep Uid|awk -F: '{print $2}'|awk -F'/' '{print $1}'|tr -cd "[0-9]")
CountPerm7=$(lsattr /etc/passwd|grep i|wc -l)
CountPerm8=$(lsattr /etc/group|grep i|wc -l)

if [ "${passwdPerm1}" -eq 0644 ] && [ "${groupPerm2}" -eq 0644 ] && [ "${mountPerm3}" -eq 4744 ] && [ "${umountPerm4}" -eq 4744 ] && [ "${crontabPerm5}" -eq 0600 ] && [ "${grubPerm6}" -eq 0600 ] && [ "${CountPerm7}" -eq 1 ] && [ "${CountPerm8}" -eq 1 ]; then
  System_Key_File_Permissions_Control_Status=$(echo "OK")
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_System_Key_File_Permissions_Control: OK"
else
  System_Key_File_Permissions_Control_Status=$(echo "ERROR")
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_System_Key_File_Permissions_Control: ERROR"
fi
}

# check_TMOUT
check_TMOUT()
{
CHECK_TMOUT_NUM=$(cat /etc/profile|grep -v ^#|grep 'TMOUT=600'|wc -l)

if [ "${CHECK_TMOUT_NUM}" -eq 1 ] ; then
  TMOUT_STATUS=$(echo "OK")
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item check_TMOUT: OK"
else
  TMOUT_STATUS=$(echo "ERROR")
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item check_TMOUT: ERROR"
fi

}

# check_HISTTIMEFORMAT
check_HISTTIMEFORMAT()
{
CHECK_HISTTIMEFORMAT_NUM=$(cat /etc/profile|grep -v ^#|grep 'HISTTIMEFORMAT="%F %T "'|wc -l)

if [ "${CHECK_HISTTIMEFORMAT_NUM}" -eq 1 ] ; then
  HISTTIMEFORMAT_STATUS=$(echo "OK")
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item check_HISTTIMEFORMAT: OK"
else
  HISTTIMEFORMAT_STATUS=$(echo "ERROR")
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item check_HISTTIMEFORMAT: ERROR"
fi

}


# check_Ctrl-Alt-Delete
check_Ctrl_Alt_Delete()
{
Ctrl_Alt_Delete_ENABLE=$(/usr/bin/systemctl is-enabled ctrl-alt-del.target)

if [[ ${Ctrl_Alt_Delete_ENABLE} == "masked" ]]; then
  Ctrl_Alt_Delete_Status=$(echo "OK")
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Ctrl_Alt_Delete: OK"
else
  Ctrl_Alt_Delete_Status=$(echo "ERROR")
  echo "$A_ADDRESS $A_DATA_TIME Redhat_System_Check_Item Check_Ctrl_Alt_Delete: ${Ctrl_Alt_Delete_ENABLE}"
fi

}

main()
{
#check_system_version
if [ -f "/etc/system-release" ]&&[ ! -z "`cat /etc/system-release|grep -i 'red hat'`" ];then
uname -r | grep el5 > /dev/null && OS_VERSION=el5
uname -r | grep el6 > /dev/null && OS_VERSION=el6
uname -r | grep el7 > /dev/null && OS_VERSION=el7
else
OS_VERSION=unknow
fi

check_host_type
# check_hostname
get_ip_address
# check_system_version
check_runlevel
check_filesystem_space
check_filesystem_inode_space
check_cpu_load
check_memory_space
check_swap_space
check_threads_number
check_zombie_number
check_dns_service
check_timesync_serivce
check_selinux_mode
check_umask_mode
check_firewalld
check_NetworkManager
check_filesystem_readonly_number
check_password_complexity
check_maximum_password_survival
check_login_failed_account_lock
check_root_remote_login
check_redundant_account_lockdown
check_system_key_file_permissions_control
check_TMOUT
check_HISTTIMEFORMAT
check_Ctrl_Alt_Delete
}

main

echo "${HOST_TYPE};${A_HOSTNAME};${A_ADDRESS};${A_OS_VERSION};${A_RUNLEVEL};${FILE_BEYOND_NUM};${FILE_BEYOND_MAX};${FILE_BEYOND_INODE_NUM};${FILE_BEYOND_INODE_MAX};${CPU_IDLE};${REAL_MEMORY};${SWAP_USE};${NUM_THREADS};${NUM_ZOMBIE};${DNS_SERVICE};${S_TIMESYNC};${GET_SELINUX};${GET_UMASK};${FIREWALLD_ACTIVE},${FIREWALLD_ENABLE};${NetworkManager_ACTIVE},${NetworkManager_ENABLE};${FILE_READ_ONLY};${PASSWORD_COMPLEXITY_STATUS};${Password_Survival_Status};${Login_Failed_Account_Lock_Status};${Root_Remote_Login_Status};${Redundant_Account_Lockdown_Status};${System_Key_File_Permissions_Control_Status};${TMOUT_STATUS};${HISTTIMEFORMAT_STATUS};${Ctrl_Alt_Delete_Status};" > /tmp/system_health_check_report.txt

